package admin.forms;

import helpers.GoogleStorageHelper;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.servlet.http.HttpServletRequest;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileReadChannel;
import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.FileServiceFactory;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.ServingUrlOptions;

import entities.Template;

public class TemplateForm {
	
	private static FileService fileService = FileServiceFactory.getFileService();
	private static BlobstoreService blobService = BlobstoreServiceFactory.getBlobstoreService();
	private static ImagesService imageService = ImagesServiceFactory.getImagesService();
	
	
	public static TreeMap<String, Object> checkValid(HttpServletRequest request, Template template) {
		TreeMap<String, Object> form = new TreeMap<String, Object>();
		TreeMap<String, String> check = new TreeMap<String, String>();
		
		String id = (String) request.getParameter("id");
		String title = (String) request.getParameter("title");
		String description = (String) request.getParameter("description");
		
		if (id == null || id.isEmpty()) {
			check.put("id", "Id is not empty.");
			template.setId("");
		} else {
			template.setId(id);
		}
		
		if (title == null || title.isEmpty()) {
			check.put("title", "Title is not empty.");
			template.setTitle("");
		} else {
			template.setTitle(title);
		}
		
		if (description == null || description.isEmpty()) {
			check.put("description", "Title is not empty.");
			template.setDescription("");
		} else {
			template.setDescription(description);
		}
		
		if (check.size() == 0) {
			try {
				/* after upload file to blob store, read file from blob store. */
				Map<String, List<BlobKey>> blobs = blobService.getUploads(request);
				/* handle thumbnail */
				List<BlobKey> blobKeys1 = blobs.get("thumb");
				try {
					if (blobKeys1 != null && blobKeys1.size() > 0) {
						for (BlobKey blobKey : blobKeys1) {
							if (blobService.fetchData(blobKey, 0, 20).length > 0) {
								AppEngineFile file = fileService.getBlobFile(blobKey);
								template
										.setThumbnail(imageService
												.getServingUrl(ServingUrlOptions.Builder
														.withBlobKey(blobKey)));
							}
						}
					}
					System.out.println("Pass get thumb");
				} catch (Exception e) {
					check.put("thumbnail", e.getMessage());
					//e.printStackTrace(System.err);
				}
				
				/* handle template data */
				try {
					List<BlobKey> blobKeys2 = blobs.get("data");
					ByteArrayOutputStream bos = new ByteArrayOutputStream();
					if (blobKeys2 != null && blobKeys2.size() > 0) {
						for (BlobKey blobKey : blobKeys2) {
							if (blobService.fetchData(blobKey, 0, 20).length > 0) {
								AppEngineFile file = fileService.getBlobFile(blobKey);
								FileReadChannel readChannel = fileService.openReadChannel(file,
										true);
								InputStream is = Channels.newInputStream(readChannel);
								int nRead;
								byte[] buffer = new byte[10240];
								/*
								 * put to byte array output stream to work with
								 * google storage
								 */
								while ((nRead = is.read(buffer, 0,
										buffer.length)) != -1) {
									bos.write(buffer, 0, nRead);
								}
								bos.flush();
							}
						}
	
						/*
						 * make byte array input stream from byte array output
						 * stream to work with Google storage
						 */
						ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
						ZipInputStream zis = new ZipInputStream(bais);
						ZipEntry entry;
	
						String tempSubFolder = "";
						boolean checkFileStructure = true;
						int count = 0;
	
						/* create upload path to Google Storage */
						String path = template.getId() + "/";
						ByteArrayOutputStream tempBAOS;
						while ((entry = zis.getNextEntry()) != null) {
							/*
							 * check if folder create by Mac Os (remove Mac OS
							 * information folder)
							 */
							if (entry.toString().contains("__MACOS")) {
								continue;
							} else {
								byte[] buffer = new byte[10240];
								tempBAOS = new ByteArrayOutputStream();
	
								int length;
								while ((length = zis.read(buffer, 0,
										buffer.length)) != -1) {
									tempBAOS.write(buffer, 0, length);
								}
	
								
									if (entry.isDirectory()) {
										if (entry.toString().contains(
												tempSubFolder)) {
											count++;
										}
										if (count == 6) {
											/* report error, too many folder */
										}
									} else {
										/*
										 * if not folder, upload file to google
										 * storage. First, check file extension.
										 */
										String extension = GoogleStorageHelper
												.getExtension(entry.toString());
										GoogleStorageHelper.uploadGoogleStorage(
												path + entry.toString(),
												extension, tempBAOS);
									}
								
							}
	
						}
						if (checkFileStructure) {
							/* save template to database and remove cache */
							template.setBaseUrl("http://"
									+ GoogleStorageHelper.BUCKETNAME + "/"
									+ template.getId() + "/");
						} else {
							check.put("dirUpload", "Invalid folder structure !");
						}
					}
				} catch (Exception e) {
					e.printStackTrace(System.err);
				}
				
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		
		
		
		form.put("checkValid", check);
		form.put("template", template);
		
		return form;
	}
}
